/*
 * SPDX-License-Identifier: Apache-2.0
 * Copyright Red Hat Inc. and Hibernate Authors
 */
package org.hibernate.annotations;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import org.hibernate.generator.AnnotationBasedGenerator;
import org.hibernate.generator.Generator;
import org.hibernate.generator.OnExecutionGenerator;
import org.hibernate.generator.BeforeExecutionGenerator;
import org.hibernate.generator.internal.TenantIdGeneration;

import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

/**
 * Meta-annotation used to mark another annotation as providing configuration
 * for a custom {@linkplain Generator value generation strategy}. This is the
 * best way to work with customized value generation in Hibernate.
 * <p>
 * For example, if we have a custom value generator:
 * <pre>
 * public class SKUGeneration
 *         implements BeforeExecutionGenerator {
 *     public SKUGeneration(SKU sku, Member annotatedMember,
 *                          GeneratorCreationContext context) {
 *         ...
 *     }
 *     ...
 * }
 * </pre>
 * <p>
 * Then we may also define an annotation which associates this generator with
 * a field or property of an entity and supplies configuration parameters:
 * <pre>
 * &#64;ValueGenerationType(generatedBy = SKUGeneration.class)
 * &#64;Retention(RUNTIME) &#64;Target({METHOD,FIELD})
 * public &#64;interface SKU {}
 * </pre>
 * <p>
 * and we may use it as follows:
 * <pre>
 * &#64;SKU String sku;
 * </pre>
 * <p>
 * No more than one generator annotation may be placed on a given property.
 * <p>
 * Adding a generator annotation to an entity property causes the value of
 * the property to be generated when any SQL statement to {@code insert} or
 * {@code update} the entity is executed.
 * <p>
 * Every generator annotation type has a {@link Generator} implementation
 * which is responsible for generating values. It must be either:
 * <ul>
 * <li>a {@link BeforeExecutionGenerator}, for values that are generated in
 *     Java code, or
 * <li>an {@link OnExecutionGenerator}, for values which are generated by
 *     the database.
 * </ul>
 * <p>
 * A generator annotation may have members, which are used to configure the
 * value generator, if either:
 * <ul>
 * <li>the value generator implements {@link AnnotationBasedGenerator}, or
 * <li>the value generator class has a constructor with the same signature
 *     as {@link AnnotationBasedGenerator#initialize}.
 * </ul>
 * <p>
 * There are several excellent examples of the use of this machinery right
 * here in this package. {@link TenantId} and its corresponding generator
 * {@link TenantIdGeneration} are a good place to start.
 * <p>
 * A {@code @ValueGenerationType} annotation must have retention policy
 * {@link RetentionPolicy#RUNTIME}.
 *
 * @see Generator
 * @see BeforeExecutionGenerator
 * @see OnExecutionGenerator
 * @see AnnotationBasedGenerator
 *
 * @author Gunnar Morling
 */
@Target(ANNOTATION_TYPE)
@Retention(RUNTIME)
public @interface ValueGenerationType {
	/**
	 * A class which implements {@link Generator}.
	 */
	Class<? extends Generator> generatedBy();
}
